#include "playcenterpanelbase.h"
#include <QApplication>
PlayCenterPanelBase::PlayCenterPanelBase(QWidget *parent,int make[],
                                         QVector<Poker*> & own_poker_v,
                                         QVector<Poker*> & other_poker_v,
                                         int *last_numer_v ,
                                         int *next_number_v,
                                         int step,
                                         int offset_height_v,
                                         int time_v ,
                                         int no_time_v ):
    GamePlayCenterPanel(parent,make,own_poker_v,other_poker_v,last_numer_v ,next_number_v),
    step_button(step),offset_height(offset_height_v),time(time_v),no_time(no_time_v),own_out_poker()
{
    //qDebug() << parent;
    init();
}

//运行流程
player_type PlayCenterPanelBase::run_game(){
    while(1){
        show_LCD(player_type::NEXT);
        for (int i =0;i < 100000;++i) {
            qApp->processEvents();
        }
        next_out_card({0});
        if(*(this->last_number) <= 0){
            break;
        }

        qApp->processEvents();

        show_LCD(player_type::LAST);
        for (int i =0;i < 100000;++i) {
            qApp->processEvents();
        }
        last_out_card({-1});

        if(*(this->next_number) <= 0){
            break;
        }
        qApp->processEvents();
        show_LCD(player_type::MY);
        while(1){
            if(isEnd) break;
            qApp->processEvents();
        }
        if(isOutAll) {
            break;
        }
    }

    return player_time;
}

void PlayCenterPanelBase::init(){
    isEnd = false;//出牌是否结束
    isOutAll = false;//游戏是否结束
    isOutPoker = false;//没有出过牌
    button_init();//按钮初始化
    //初始化显示器，并将其隐藏
    lcd = new QLCDNumber((QWidget *)this->parent());
    lcd->hide();
    //初始化计时器
    timer = new QTimer(this);
    set_all_label();//初始化标签
    no_out_count = 0;//不出个数为0
    own_out_poker.clear();
    add_poker_connection();//给牌添加信号
    last_number_temp = *(this->last_number);
    next_number_temp = *(this->next_number);
}

//给牌添加信号
void PlayCenterPanelBase::add_poker_connection(){

    //获取最小y坐标
    int min_y = own_poker[0]->y();
    bool isChange = false;
    foreach (Poker * poker, this->own_poker) {
        if(poker->y() < min_y){
            min_y = poker->y();
            isChange = true;
        }
    }
    //如果改变了
    if(isChange){
        //将突出的牌加入到own_out_poker
        foreach (Poker * poker, this->own_poker) {
            if(poker->y() == min_y){
                own_out_poker.push_back(poker);
            }
        }
    }

    //添加信号连接
    foreach (Poker * poker, this->own_poker) {
        connect(poker,&Poker::pos_changed,this,&PlayCenterPanelBase::add_out_poker);
    }
}

//设置标签
void PlayCenterPanelBase::set_all_label(){
    QWidget * parent = (QWidget *)this->parent();
     qDebug() << parent;
    last_no_out_label = new QLabel("不出",parent);//不出标签
    next_no_out_label = new QLabel("不出",parent);//不出标签
    my_no_out_label = new QLabel("不出",parent);//不出标签
    qDebug() << "标签设置";
    last_number_label = new QLabel(QString("%1张").arg(*(this->last_number)),parent);//上家的牌个数标签
    last_number_label->move(this->last_space.width()/2,this->last_space.height() - 80);
    last_number_label->show();

    next_number_label = new QLabel(QString("%1张").arg(*(this->next_number)),parent);//下家的牌个数标签
    next_number_label->move(this->next_space.x() + this->next_space.width()/2,this->next_space.height() - 80);
    next_number_label->show();

    //自己牌的个数
    my_number_label = new QLabel(QString("%1张").arg(this->own_poker.size()),parent);//自己的牌个数标签
    my_number_label->move(this->own_space.width()/2,890);
    my_number_label->show();
}




//上家出牌，传入出牌序列，如果只有-1，那么就表示不出牌
void PlayCenterPanelBase::last_out_card(const QVector<int> & poker_number) {
    close_lcd_timer();//停止计时，关闭lcd
    if(poker_number[0] == -1){//如果不需要出牌
        //不出计数
        ++no_out_count;
        if(no_out_count == 2){
            need_cmp_poker.clear();
            no_out_count = 0;
        }
        //显示不出在中间
        last_no_out_label->move(this->out_card_space.x() + 20,this->out_card_space.height()/2);
        last_no_out_label->show();

        return;
    }
    need_cmp_poker.clear();//清空带比较数组
    int len = poker_number.size();//看出了多少张牌
    QVector<int>::const_iterator it =  poker_number.begin();

    //改变上家牌的位置
    int lost = last_number_temp - *(this->last_number);
    int start = lost/2 + lost % 2;
    int end = last_number_temp - 1 - lost/2;
    bool isUp = lost % 2 ? false : true;//上下标记，true则上移动到中央，false则下移动到中央
    for (int i = 0;i < len;++i ) {
        int index = *(it++);
        if(isUp){//如果
            //修改牌的贴图
            this->other_poker[start]->reset_Pixmap(index);
            //将上家牌放入集合中
            last_out_all_poker.push_back(this->other_poker[start]);
            //将比较的牌放入带比较集合
            need_cmp_poker.push_back(this->other_poker[start]);
            //修改牌的位置和层次
            this->other_poker[start]->move(this->out_card_space.x()+20+i*20,this->out_card_space.height()/2);
            this->other_poker[start]->raise();
            //修改mark数组
            ++this->poker_mark[index];
            //修改上家牌的数量
            --(*this->last_number);
            //修改当前显示张数
            last_number_label->setText(QString("%1张").arg(*(this->last_number)));
            //偏移量
            ++start;
        }else{
            this->other_poker[end]->reset_Pixmap(index);//修改图片
            last_out_all_poker.push_back(this->other_poker[end]);
            need_cmp_poker.push_back(this->other_poker[end]);
            this->other_poker[end]->move(this->out_card_space.x()+20+i*20,this->out_card_space.height()/2);//改变位置
            this->other_poker[end]->raise();
            ++this->poker_mark[index];//修改mark数组
            --(*this->last_number);//增加上家牌
            last_number_label->setText(QString("%1张").arg(*(this->last_number)));
            --end;
        }
        isUp = !isUp;
    }

}
void PlayCenterPanelBase::next_out_card(const QVector<int> & poker_number){
    close_lcd_timer();//停止计时，关闭lcd

    if(poker_number[0] == -1){//如果不需要出牌
        ++no_out_count;
        if(no_out_count == 2){
            need_cmp_poker.clear();
            no_out_count = 0;
        }
        //显示在中间
        next_no_out_label->move(this->out_card_space.x() + this->out_card_space.width(),this->out_card_space.height()/2);
        next_no_out_label->show();
        return;
    }
    need_cmp_poker.clear();//清空带比较数组
    int len = poker_number.size();//看出了多少张牌
    QVector<int>::const_iterator it =  poker_number.begin();

    //改变下家牌的位置
    int lost = next_number_temp - *(this->next_number);
    int start = lost/2 + lost % 2;
    int end = next_number_temp - 1 - lost/2;
    bool isUp = lost % 2 ? false : true;//上下标记，true则上移动到中央，false则下移动到中央
    for (int i = 0;i < len;++i ) {
        int index = *(it++);
        if(isUp){
            this->other_poker[last_number_temp+start]->reset_Pixmap(index);
            next_out_all_poker.push_back(this->other_poker[last_number_temp+start]);
            need_cmp_poker.push_back(this->other_poker[last_number_temp+start]);
            this->other_poker[last_number_temp+start]->move(this->out_card_space.x() + this->out_card_space.width()-STEP*i,this->out_card_space.height()/2);
            this->other_poker[last_number_temp+start]->lower();
            ++this->poker_mark[index];
            --(*this->next_number);
            next_number_label->setText(QString("%1张").arg(*(this->next_number)));
            ++start;
        }else{
            this->other_poker[last_number_temp+end]->reset_Pixmap(index);//修改图片
            next_out_all_poker.push_back(this->other_poker[last_number_temp+end]);
            need_cmp_poker.push_back(this->other_poker[last_number_temp+end]);
            this->other_poker[last_number_temp+end]->move(this->out_card_space.x() + this->out_card_space.width()-STEP*i,this->out_card_space.height()/2);//改变位置
            this->other_poker[last_number_temp+end]->lower();
            ++this->poker_mark[index];//修改mark数组
            --(*this->next_number);//增加上家牌
            next_number_label->setText(QString("%1张").arg(*(this->next_number)));
            --end;
        }
        isUp = !isUp;
    }

}
//添加一张牌到对应玩家序列出牌序列
void PlayCenterPanelBase::add_out_poker(bool isUp,Poker * poker){
    //如果牌上升了，就就将牌添加，否则删除
    if(isUp){
        qDebug() << "添加:" << poker;
        own_out_poker.push_back(poker);
//        foreach (const Poker * poker, own_out_poker) {
//           qDebug() << poker;
//        }

        if(player_time == player_type::MY ){
            if(test_can_out())
                out->show();
            else{
                out->hide();
            }
        }else{
            out->hide();
        }
    }else {
        bool isOK = own_out_poker.removeOne(poker);
        if(isOK){
            qDebug() << "删除成功";
            if(player_time == player_type::MY ){
                if(test_can_out())
                    out->show();
                else{
                    out->hide();
                }
            }else{
                out->hide();
            }
        }else{
            qDebug() << "删除失败";
        }
    }
}
//判断出牌的n个是否一样
bool PlayCenterPanelBase::isSame(int n) const{
    if(n < 1 || n > 4) return false;
    if(own_out_poker.at(0)->getIndex() == 52 || own_out_poker.at(0)->getIndex() == 53) return false;
    int temp = own_out_poker.at(0)->getIndex() % 13;
    int i = 1;
    for(;i < n;++i){
        if(own_out_poker.at(i)->getIndex() % 13 != temp) break;
        if(own_out_poker.at(i)->getIndex() == 52 || own_out_poker.at(i)->getIndex() == 53) break;
    }
    if(i < n) return false;
    else return true;
}

//判断出牌序列是否能够出牌
bool PlayCenterPanelBase::test_can_out() const{
    qDebug() << "自己的牌";
    foreach (const Poker *poker, own_out_poker) {
        qDebug() << poker->getIndex();
    }
    qDebug() << "带比较的牌";
    foreach (const Poker *poker, need_cmp_poker) {
        qDebug() << poker->getIndex();
    }
    qDebug() << "----------------";

    //先判断牌的个数
    int need = need_cmp_poker.size();
    int own = own_out_poker.size();

    //王炸第一
    //别人王炸
    if(need == 2){
        if(need_cmp_poker.at(0)->getIndex() == 52 ){
            if(need_cmp_poker.at(1)->getIndex() == 53) return false;
        }
        if(need_cmp_poker.at(0)->getIndex() == 53 ){
            if(need_cmp_poker.at(1)->getIndex() == 52) return false;
        }
    }
    //自己王炸
    if(own == 2){
        if(own_out_poker.at(0)->getIndex() == 52 ){
            if(own_out_poker.at(1)->getIndex() == 53) return true;
        }
        if(own_out_poker.at(0)->getIndex() == 53 ){
            if(own_out_poker.at(1)->getIndex() == 52) return true;
        }
    }
    if(need == 0){
        if(own == 0) {
            qDebug() << "0 0 比较";
            return false;
        }
        else if(own == 1) {
            qDebug() << "0 1 比较";
            return true;
        }
        else if(own <= 4 || own >= 2) {
            qDebug() << "0 " << own <<" 比较";
            return isSame(own);
        }
    }else if(need == 1){//如果被比较的牌数量为1
        if(own == 1){
            int own_index = own_out_poker.at(0)->getIndex();
            int need_index = need_cmp_poker.at(0)->getIndex();
            //如果自己出的是大小王
            if(own_index >= 52 ){
                     if(own_index > need_index )//自己比大小王大
                         return true;
                     return false;
            }
            //如果自己不是大小王,取模13运算
            if(own_index % 13 > need_index % 13)
                return true;
            qDebug() << "1 1 比较";
            return false;
        }
        else if(own == 3) return isSame(own);
        else return false;
    }else if(need == 2){//如果被比较的牌数量为2
        if(own == 2){
            if(isSame(own)){//如果是相同的，判断是否大
                qDebug() << "2 2 比较";
                if(own_out_poker.at(0)->getIndex() % 13 > need_cmp_poker.at(0)->getIndex() % 13) return true;
                else return false;
            }
        }else if(own == 4){
            qDebug() << "2 4 比较";
            return isSame(own);
        }else return false;
    }else if(need == 3){//如果被比较的牌数量为3
        if(own == 3){
            if(isSame(own)){//如果是相同的，判断是否大
                qDebug() << "3 3 比较";
                if(own_out_poker.at(0)->getIndex() % 13 > need_cmp_poker.at(0)->getIndex() % 13) return true;
                else return false;
            }
        }else if(own == 4){
            qDebug() << "3 4 比较";
            return isSame(own);
        }else return false;
    }else if(need == 4){
        if(own == 4){
            if(isSame(own)){//如果是相同的，判断是否大
                qDebug() << "4 4 比较";
                if(own_out_poker.at(0)->getIndex() % 13 > need_cmp_poker.at(0)->getIndex() % 13) return true;
                else return false;
            }
        }
    }
    return false;
}

//根据玩家类型显示显示器并开始计时，并根据玩家类型发送信号
void PlayCenterPanelBase::show_LCD(player_type player_type_v){
    if(player_type_v == player_type::LAST){//上家计时器
        //隐藏上家不出
        last_no_out_label->hide();
        //隐藏上家扑克牌
        foreach (Poker * p, last_out_all_poker) {
            p->hide();
        }
        lcd->move(this->out_card_space.x() + 20,this->out_card_space.height()/2);//显示上家LCD位置
        //显示
        lcd->display(time);
        lcd->show();
        if(timer->isActive())
            timer->stop();
        connect(timer,&QTimer::timeout,this,&PlayCenterPanelBase::change_lcd_num);
        timer->start();
    }else if(player_type_v == player_type::NEXT){//下家计时器
        //隐藏下家不出
        next_no_out_label->hide();
        //隐藏下家扑克牌
        foreach (Poker * p, next_out_all_poker) {
            p->hide();
        }
        lcd->move(this->out_card_space.x() + this->out_card_space.width(),this->out_card_space.height()/2);//显示下家LCD位置
        //显示
        lcd->display(time);
        lcd->show();
        if(timer->isActive())
            timer->stop();
        connect(timer,&QTimer::timeout,this,&PlayCenterPanelBase::change_lcd_num);
        timer->start();
    }else if(player_type_v == player_type::MY){
        qDebug() << "no_out_count" << no_out_count;
        if(no_out_count == 0 && need_cmp_poker.isEmpty()) no_out->hide();
        else {
            no_out->show();
            no_out_count = 0;
        }
        isOutPoker = false;
        isEnd = false;
        //隐藏自己不出
        my_no_out_label->hide();
        //隐藏自己的扑克牌
        foreach (Poker * p, my_out_all_poker) {
            p->hide();
        }
        //显示不出和提示按钮
        tips->show();
        //根据判断结果显示出牌
        if(test_can_out()){
            out->show();
        }else{
            out->hide();
        }
        //移动lcd
        lcd->move(this->own_space.x() + this->own_space.width()/2-lcd->width()/2,this->out_card_space.height()-100);
        //显示
        lcd->display(time);
        lcd->show();
        if(timer->isActive())
            timer->stop();
        connect(timer,&QTimer::timeout,this,&PlayCenterPanelBase::change_lcd_num);
        timer->start();
    }
    player_time = player_type_v;
}

void PlayCenterPanelBase::close_lcd_timer(){
    if(timer->isActive())
        timer->stop();
    disconnect(timer,&QTimer::timeout,this,&PlayCenterPanelBase::change_lcd_num);
    lcd->hide();
}

void PlayCenterPanelBase::change_lcd_num(){
    lcd->display(static_cast<int>(lcd->value())-1);
    if(static_cast<int>(lcd->value()) < 0){
        qDebug() << "倒计时结束" ;
        //关闭倒计时，并解除信号连接
        close_lcd_timer();
        //根据当前玩家类型发送信号
        if(player_time == player_type::MY){
            no_out_poker();
        }else{
            emit other_out_card_end();
        }
    }else{
        timer->start(1000);
    }
}


void PlayCenterPanelBase::button_init(){

    QWidget* parent_ = (QWidget *)this->parent();
    //按钮设置
    out = new QPushButton(parent_);//设置出牌按钮
    out->setText("出牌");
    out->hide();

    //连接
    connect(out,&QPushButton::clicked,this,&PlayCenterPanelBase::out_poker);

    no_out = new QPushButton(parent_);//设置不出牌按钮
    no_out->setText("不出");
    no_out->hide();
    connect(no_out,&QPushButton::clicked,this,&PlayCenterPanelBase::no_out_poker);

    tips = new QPushButton(parent_);//设置提示按钮
    tips->setText("提示");
    tips->hide();

    //计算按钮位置
    int no_out_x = this->own_space.width()/2-no_out->width()/2;
    int out_x = no_out_x - step_button - out->width();
    int tips_x = out_x + out->width()+2*step_button+no_out->width();

    //设置按钮位置
    out->move(out_x,this->own_space.y()-offset_height);
    no_out->move(no_out_x,this->own_space.y()-offset_height);
    tips->move(tips_x,this->own_space.y()-offset_height);

}

//不出
void PlayCenterPanelBase::no_out_poker(){
    my_no_out_label->move(this->own_space.width()/2,this->own_space.y() - 50);
    my_no_out_label->show();
    //关闭lcd和timer连接
    close_lcd_timer();
    //隐藏所有按钮
    set_show_other_button(false);
    out->hide();
    isEnd = true;
}

void PlayCenterPanelBase::out_poker(){
    if(isOutPoker) {
        return;
    }
    //添加到自己已经出的数组
    my_out_all_poker.append(own_out_poker);
    //关闭lcd和timer连接
    close_lcd_timer();
    //隐藏所有按钮
    set_show_other_button(false);
    out->hide();
    //移动所有牌
    //int out_poker_y = own_out_poker.at(0)->y();//将要出的牌的y坐标
    //int will_out_poker = 0;//own_out_poker
    foreach (Poker * will_out_poker, own_out_poker) {
        //获取将要出的牌的序号
        int poker_index = own_poker.indexOf(will_out_poker);
        //如果牌在整个区域左侧，那么比它小的全部右移，反之左移
        //自己隐藏
        own_poker[poker_index]->hide();
        if(own_poker[poker_index]->x() < this->own_space.width()/2){
            for(int i = 0;i < poker_index;++i){
                   own_poker[i]->move(own_poker[i]->x()+STEP,own_poker[i]->y());
                   }
        }else{
            for(int i = poker_index + 1;i < own_poker.size();++i){
                   own_poker[i]->move(own_poker[i]->x()-STEP,own_poker[i]->y());
            }
        }
    }
    //移动牌到出牌区域
    //左开始下标
    int pos_x = own_space.width()/2 - ((own_out_poker.size() - 1)*STEP+own_out_poker.at(0)->width())/2;
    int pos_y = own_space.y() - own_out_poker.at(0)->height()-50;
    int offset_n = 0;//偏移个数
    foreach (Poker * will_out_poker, own_out_poker) {
        will_out_poker->move(pos_x+STEP*offset_n++,pos_y);
        will_out_poker->show();
        will_out_poker->raise();
        disconnect(will_out_poker,&Poker::pos_changed,this,&PlayCenterPanelBase::add_out_poker);
        will_out_poker->setCanClick(false);
    }
    //清空出牌
    own_out_poker.clear();
    isEnd = true;
    qDebug() << "曾经出过的牌：" << my_out_all_poker.size();
    qDebug() << "自己的牌：" << own_poker.size();
    //修改牌数的标签
    my_number_label->setText(QString("%1张").arg(own_poker.size() - my_out_all_poker.size()));
    //是否出完牌
    if(my_out_all_poker.size() == own_poker.size()) isOutAll = true;
    isOutPoker = true;
}

PlayCenterPanelBase::~PlayCenterPanelBase(){
    delete lcd;
}
